//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "Pratt2PatternsByCATH.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
#include <fstream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHTEXT 1000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH::Pratt2PatternsByCATH () {
  
  this->namefile               = new String ();
  this->namefileOut            = new String ();

  this->listNamefiles          = new TListE <String> ();
  this->listGroupPrattPatterns = new TListE <Pratt2Patterns> ();

  this->toString               = new String ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH::Pratt2PatternsByCATH (const Pratt2PatternsByCATH& pratt2PatternsByCATH) {
  
  this->namefile               = new String (pratt2PatternsByCATH.namefile);
  this->namefileOut            = new String (pratt2PatternsByCATH.namefileOut);

  this->listNamefiles          = new TListE <String> (pratt2PatternsByCATH.listNamefiles);
  this->listGroupPrattPatterns = new TListE <Pratt2Patterns> (pratt2PatternsByCATH.listGroupPrattPatterns);

  this->toString               = new String ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH::Pratt2PatternsByCATH (const Pratt2PatternsByCATH* pratt2PatternsByCATH) {
  
  this->namefile               = new String (pratt2PatternsByCATH->namefile);
  this->namefileOut            = new String (pratt2PatternsByCATH->namefileOut);

  this->listNamefiles          = new TListE <String> (pratt2PatternsByCATH->listNamefiles);
  this->listGroupPrattPatterns = new TListE <Pratt2Patterns> (pratt2PatternsByCATH->listGroupPrattPatterns);

  this->toString               = new String ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH::~Pratt2PatternsByCATH () {
  
  if (this->namefile)               delete this->namefile;
  if (this->namefileOut)            delete this->namefileOut;
  if (this->listNamefiles)          delete this->listNamefiles;
  if (this->listGroupPrattPatterns) delete this->listGroupPrattPatterns;
  if (this->toString)               delete this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void Pratt2PatternsByCATH::Namefile (String* namefile) {
  
  if (namefile) this->namefile->In(namefile);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void Pratt2PatternsByCATH::NamefileOut (String* namefileOut) {
  
  if (namefileOut) this->namefileOut->In(namefileOut);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void Pratt2PatternsByCATH::ListNamefiles (TListE <String>* listNamefiles) {
  
  if (listNamefiles) *(this->listNamefiles) = *(listNamefiles);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void Pratt2PatternsByCATH::ListGroupPrattPatterns (TListE <Pratt2Patterns>* listGroupPrattPatterns) {
  
  if (listGroupPrattPatterns) *(this->listGroupPrattPatterns) = *(listGroupPrattPatterns);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* Pratt2PatternsByCATH::Namefile (void) {
  
  return this->namefile;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* Pratt2PatternsByCATH::NamefileOut (void) {
  
  return this->namefileOut;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <String>* Pratt2PatternsByCATH::ListNamefiles (void) {
  
  return this->listNamefiles;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <Pratt2Patterns>* Pratt2PatternsByCATH::ListGroupPrattPatterns (void) {
  
  return this->listGroupPrattPatterns;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool Pratt2PatternsByCATH::LoadDataFromListFiles (void) {

  if (!this->listNamefiles || !this->listNamefiles->Length()) return false;
  
  int counter = 0;
    
  this->listNamefiles->SetInitial();
  while (this->listNamefiles->SetNext()) {
    
    Pratt2Patterns* newPratt2Patterns = new Pratt2Patterns ();
    
    newPratt2Patterns->Namefile(this->listNamefiles->GetCurrent());
    newPratt2Patterns->Code(++counter);
    
    cout << "Read data from: " << this->listNamefiles->GetCurrent()->Out() << endl;
    
    if (!newPratt2Patterns->LoadDataFromFile()) 
      delete newPratt2Patterns;
    else
      this->listGroupPrattPatterns->Add(newPratt2Patterns);
    
  }
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool Pratt2PatternsByCATH::LoadData (void) {
  
  if (!this->namefile || !this->namefile->Length()) return false;
  
  this->listGroupPrattPatterns->Clear();
  
  ifstream file (this->namefile->Out());
  
  char     buffer [LENGTHTEXT + 1];
  String   stringBuffer;
  
  bool     patternCond = false;
  bool     matchesCond = false;
  
  if (!file.is_open()) return false;
  
  while (!file.eof()) {
    
    file.getline(buffer, LENGTHTEXT);
    stringBuffer.In(buffer);
    stringBuffer.Trim();
    
    if (!stringBuffer.Length()) continue;
    
    if (stringBuffer.Contain("Patterns Records")) {
      patternCond = true;
      continue;
    }
    
    if (stringBuffer.Contain("Matches Records")) {
      patternCond = false;
      matchesCond = true;
      continue;
    }
    
    if (stringBuffer.Contain("End File")) {
      patternCond = false;
      matchesCond = false;
      break;
    }
    
    if (!patternCond && !matchesCond) {
      
      Pratt2Patterns* newPratt2Patterns = new Pratt2Patterns ();
      
      int             code;   
      int             numberSeq;       //Analyzing # sequences from file input

      int             cM;              //CM: min Nr of Seqs to Match
      double          cPercent;        //C%: min Percentage Seqs to Match            (90, 80, 60, 40, 20)

      char            pP [20];         //PP: pos in seq [off,complete,start]         off
      int             pL;              //PL: max Pattern Length                      50
      int             pN;              //PN: max Nr of Pattern Symbols               50
      int             pX;              //PX: max Nr of consecutive x's               5
      int             fN;              //FN: max Nr of flexible spacers              3
      int             fL;              //FL: max Flexibility                         5
      int             fP;              //FP: max Flex.Product                        104
      int             bI;              //BI: Input Pattern Symbol File               off
      int             bN;              //BN: Nr of Pattern Symbols Initial Search    20

      char            s [20];          //S: Scoring [info,mdl,tree,dist,ppv]         info

      char            g [20];          //G: Pattern Graph from [seq,al,query]        seq
      int             e;               //E: Search Greediness                        3
      int             r;               //R: Pattern Refinement                       on
      int             rG;              //RG: Generalize ambiguous symbols            on

      char            oF [LENGTHTEXT]; //OF: Output Filename                        output
      int             oP;              //OP: PROSITE Pattern Format                  on
      int             oN;              //ON: max number patterns                     5000
      int             oA;              //OA: max number Alignments                   0
      int             m;               //M: Print Patterns in sequences              on
      int             mR;              //MR: ratio for printing                      10
      int             mV;              //MV: print vertically                        off
      
      sscanf(buffer, "Code:%d #Seqs:%d CM:%d C%%:%lf PP:%s PL:%d PN:%d PX:%d FN:%d FL:%d FP:%d BI:%d BN:%d S:%s G:%s E:%d R:%d RG:%d OF:%s OP:%d ON:%d OA:%d M:%d MR:%d MV:%d%*s", 
                      &code,&numberSeq,&cM,&cPercent,pP,  &pL,  &pN,  &pX,  &fN,  &fL,  &fP,   &bI, &bN,   s,   g,  &e,  &r,  &rG,   oF,  &oP,  &oN,  &oA,  &m,  &mR,  &mV);
      
      newPratt2Patterns->Code(code);
      newPratt2Patterns->NumberSeq(numberSeq);
      newPratt2Patterns->CM(cM);
      newPratt2Patterns->CPercent(cPercent);
      newPratt2Patterns->PP()->In(pP);
      newPratt2Patterns->PL(pL);
      newPratt2Patterns->PN(pN);
      newPratt2Patterns->PX(pX);
      newPratt2Patterns->FN(fN);
      newPratt2Patterns->FL(fL);
      newPratt2Patterns->FP(fP);
      newPratt2Patterns->BI((bool)bI);
      newPratt2Patterns->BN(bN);
      newPratt2Patterns->S()->In(s);
      newPratt2Patterns->G()->In(g);
      newPratt2Patterns->E(e);
      newPratt2Patterns->R((bool)r);
      newPratt2Patterns->RG((bool)rG);
      newPratt2Patterns->OF()->In(oF);
      newPratt2Patterns->OP((bool)oP);
      newPratt2Patterns->ON(oN);
      newPratt2Patterns->OA(oA);
      newPratt2Patterns->M((bool)m);
      newPratt2Patterns->MR(mR);
      newPratt2Patterns->MV((bool)mV);
      
      this->listGroupPrattPatterns->Add(newPratt2Patterns);
      
    }
    
    if (patternCond) {
      
      PatternRecord* newPatternRecord = new PatternRecord ();
      
      char   pattern [LENGTHTEXT];
      
      int    paramCode;

      int    hits;
      int    seq;

      double fitness;
      double probability = 0;
      double weight      = 0;
      
      sscanf(buffer, "%2d %4d %4d %10lf %10lf %10lf %s\0", &paramCode, &hits, &seq, &fitness, &probability, &weight, pattern);
      
      newPatternRecord->ParamCode(paramCode);
      newPatternRecord->Hits(hits);
      newPatternRecord->Seq(seq);
      newPatternRecord->Fitness(fitness);
      newPatternRecord->Probability(probability);
      newPatternRecord->Weight(weight);
      newPatternRecord->Pattern()->In(pattern);
      
      this->listGroupPrattPatterns->SetInitial();
      while (this->listGroupPrattPatterns->SetNext()) 
        if (this->listGroupPrattPatterns->GetCurrent()->Code() == paramCode) {
          this->listGroupPrattPatterns->GetCurrent()->Patterns()->Add(newPatternRecord);
          break;
        }
      
    }
    
    if (matchesCond) {
      
      int  paramCode;

      char code [20];
      char matches [LENGTHTEXT];
      
      sscanf(buffer, "%d %s %s\0", &paramCode, code, matches);
      
      PatternMatches* newPatternMatches = new PatternMatches (paramCode, code, matches);
      
      this->listGroupPrattPatterns->SetInitial();
      while (this->listGroupPrattPatterns->SetNext()) 
        if (this->listGroupPrattPatterns->GetCurrent()->Code() == paramCode) {
          this->listGroupPrattPatterns->GetCurrent()->Matches()->Add(newPatternMatches);
          break;
        }
      
    }
    
  }
  
  file.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool Pratt2PatternsByCATH::CreateCompactPatternFile (void) {
  
  if (!this->namefileOut || !this->namefileOut->Length()) return false;
  
  ofstream fileOut (this->namefileOut->Out());
  
  if (!fileOut.is_open()) return false;
  
  this->listGroupPrattPatterns->SetInitial();
  while (this->listGroupPrattPatterns->SetNext())
    fileOut << this->listGroupPrattPatterns->GetCurrent()->ToStringParameters()->Out() << endl;
  
  fileOut << endl << "Patterns Records" << endl << endl;
  
  this->listGroupPrattPatterns->SetInitial();
  while (this->listGroupPrattPatterns->SetNext()) {
    
    Pratt2Patterns* currentPratt2Patterns = this->listGroupPrattPatterns->GetCurrent();
    
    currentPratt2Patterns->Patterns()->SetInitial();
    while (currentPratt2Patterns->Patterns()->SetNext()) 
      fileOut << currentPratt2Patterns->Patterns()->GetCurrent()->ToString()->Out() << endl;
    
    fileOut << endl;

  }
  
  fileOut << "Matches Records" << endl << endl;
  
  this->listGroupPrattPatterns->SetInitial();
  while (this->listGroupPrattPatterns->SetNext()) {
    
    Pratt2Patterns* currentPratt2Patterns = this->listGroupPrattPatterns->GetCurrent();
    
    currentPratt2Patterns->Matches()->SetInitial();
    while (currentPratt2Patterns->Matches()->SetNext())
      fileOut << currentPratt2Patterns->Matches()->GetCurrent()->ToString()->Out() << endl;
    
    fileOut << endl;
    
  }
  
  fileOut << endl << "End File" << endl;
  
  fileOut.close();
  
  return true;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
Pratt2PatternsByCATH Pratt2PatternsByCATH::operator= (const Pratt2PatternsByCATH& pratt2PatternsByCATH) {
  
  this->namefile->In(pratt2PatternsByCATH.namefile);
  this->namefileOut->In(pratt2PatternsByCATH.namefileOut);

  *(this->listNamefiles)          = *(pratt2PatternsByCATH.listNamefiles);
  *(this->listGroupPrattPatterns) = *(pratt2PatternsByCATH.listGroupPrattPatterns);
    
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
